#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
# File Name: ini.sh
# Author: GID5564
# Description:
# Created Time: 03/07/22-15:54:43
#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
#! /usr/bin/bash

#${field} INI文件Field ； 
#${key} INI文件 key ；
#${value} key的新值


# 避免重复导入
#[[ -n $__XLIB_IMPORTED__INI ]] && return 0
#__XLIB_IMPORTED__INI=1

function __ini_init__() {
    wait
}


##♥♥♥♥

function read_ini(){
    local file=$1
    local field=$2
    local key=$3
    local value=$(read_ini_file ${file} ${field} ${key})
    echo ${value}
    unset file
    unset field
    unset key
    unset value
}
function write_ini(){
    local file=$1
    local field=$2
    local key=$3
    local value=$4
    write_ini_file ${file} ${field} ${key} ${value}
    unset file
    unset field
    unset key
    unset value
}
function get_sections(){
    local file=$1
    local sections
    sections=$(get_section_list ${file})
    echo ${sections}
    unset sections
}
function get_keys(){
    local file=$1
    local section=$2
    local keys
    keys=$(get_key_list ${file} ${section})
    echo ${keys}
    unset section
}
# 定义一个函数，用于检查文件是否存在、非空且可读
function _check_file(){
    # 获取文件路径作为参数
    local file_path="$1"
    
    # 检查文件是否存在、非空且可读
    if [ -f "$file_path" ] && [ -s "$file_path" ] && [ -r "$file_path" ]; then
        # 如果条件满足，返回0表示成功
        return 0
    else
        # 输出错误信息
        error "${BLUE}文件${RESET}${YELLOW}${file_path}${RESET}${BLUE}无效或不存在!${RESET}"
        # 返回1表示失败
        return 1
    fi
}


########################################
# 描述: 读取ini文件
# 参数: $1: 文件名称
#       $2: section名称
#       $3: option名称
# 返回: 如果未指定section，则列出所有的sections；如果指定了section但未指定option，则列出该section下的所有options；如果同时指定了section和option，则获取对应的值 
# 实例: read_ini_file <file> [section] [option]
########################################
function read_ini_file(){
    local iniFile=$1
    local section=$2
    local option=$3
    local iniValue='default'
    local iniOptions=()
    local iniSections=()
    local allSections
    #检查文件
    if ! _check_file ${iniFile};then
        return 1
    fi
    
    
    if [ "${section}" = "" ];then
        #通过如下两条命令可以解析成一个数组
        allSections=$(awk -F '[][]' '/\[.*]/{print $2}' ${iniFile})
        iniSections=(`echo $allSections | awk -v RS='' '{gsub("\n"," "); print}'`)
        
        msg "${BLUE}字段数:${RESET}${RED}${#iniSections[@]}${RESET} ${BLUE}字段名:[ ${RESET}${RED}${iniSections[@]} ]${RESET}"
        
    elif [ "${section}" != "" ] && [ "${option}" = "" ];then
        #判断section是否存在
        allSections=$(awk -F '[][]' '/\[.*]/{print $2}' ${iniFile})
        echo $allSections|grep ${section}
        if [ "$?" = "1" ];then
            error "${BLUE}字段名${RESET}${YELLOW}${section}${RESET}${BLUE}不存在!${RESET}"
            return 1
        fi
        #正式获取options
        #a=(获取匹配到的section之后部分|去除第一行|去除注释(#;)|去除空行|去除每一行行首行尾空格|将行内空格变为@G@(后面分割时为数组时，空格会导致误拆))
        local a=$(awk "/\[${section}\]/{a=1}a==1"  ${iniFile}|sed -e '1d' -e "/^[#;]/d" -e '/^$/d' -e 's/[ \t]*$//g' -e 's/^[ \t]*//g' -e 's/[ ]/@G@/g' -e '/\[/,$d' )
        
        local b=(`echo $a | awk -v RS='' '{gsub("\n"," "); print}'`)
        local n=${#b[@]}
        local i
        for ((i=1,j=1;i<=n;i++))
        do
          #剔除非法字符，转换@G@为空格并添加到数组尾
          local temp=${b[$i]}
          if [[ -n "${temp}" ]] || [[ "${temp}" != "@G@" ]];then
            
            local temp_n=${temp//@G@/ }
            iniOptions[$j]=${temp_n%%=*}
            unset temp_n
            #iniOptions[$j]=${${temp//@G@/ }%%=*} #可能bash嵌套不行
            ((j++))
          fi
          unset temp
        done
        msg "${BLUE}当前字段[${RESET}${RED}${section}${RESET}${BLUE}]关键字数:${RESET}${RED}${#iniOptions[@]}${RESET} ${BLUE}关键字名:[ ${RESET}${RED}${iniOptions[@]}${RESET}${BLUE}]${RESET}"
        unset a b n i
    elif [ "${section}" != "" ] && [ "${option}" != "" ];then
 
       # iniValue=`awk -F '=' '/\['${section}'\]/{a=1}a==1&&$1~/'${option}'/{print $2;exit}' $iniFile|sed -e 's/^[ \t]*//g' -e 's/[ \t]*$//g'`
        iniValue=`awk -F '=' "/\[${section}\]/{a=1}a==1" ${iniFile}|sed -e '1d' -e '/^[#;]/d' -e '/^$/d' -e '/^\[.*\]/,$d' -e "/^${option}.*=.*/!d" -e "s/^${option}.*= *//"`
        echo ${iniValue}
    fi
    unset iniFile section option iniValue iniOptions iniSections allSections
}


#
########################################
# 描述: 写入ini文件
# 参数: $1: 文件名称
#       $2: section名称
#       $3: option名称
#       $4: value值
# 返回: 
# 实例: write_ini_file <file> [section] [option] [value]
########################################
function write_ini_file(){
    local iniFile=$1
    local section=$2
    local option=$3
    local value=$4
    local iniOptions=()
    local iniSections=()
    local allSections
    local sectionFlag
    local sectionNum
    local temp
    
    #检查文件
    if ! _check_file ${iniFile};then
        return 1
    fi
    #特殊字符前加"\"
    #value=$(transf ${value})
    allSections=$(awk -F '[][]' '/\[.*]/{print $2}' ${iniFile})
    iniSections=(`echo $allSections | awk -v RS='' '{gsub("\n"," "); print}'`)
    #判断是否要新建section
    sectionFlag="0"
    for temp in ${iniSections[@]};do
        if [ "${temp}" == "${section}" ];then
            sectionFlag="1"
            break
        fi
    done
 
    if [ "$sectionFlag" = "0" ];then
        echo "[${section}]" >>${iniFile}
    fi
    
    #加入或更新value
    awk "/\[${section}\]/{a=1}a==1" ${iniFile}|sed -e '1d' -e "/^[#;]/d" -e '/^$/d'  -e 's/[ \t]*$//g' -e 's/^[ \t]*//g' -e '/\[/,$d'|grep "${option}.\?=">/dev/null
    
    if [ $? -eq 0 ];then
        #更新
        #找到制定section行号码
        sectionNum=$(sed -n -e "/\[${section}\]/=" ${iniFile})
        sed -i "${sectionNum},/^\[.*\]/s/\(${option}.\?=\).*/\1 ${value}/g" ${iniFile}
        
        #msg "成功更新 [$iniFile][$section][$option][$value]"
    else
        #新增
        #echo sed -i "/^\[${section}\]/a\\${option}=${value}" ${iniFile}
        sed -i "/^\[${section}\]/a\\${option} = ${value}" ${iniFile}
        #msg "成功添加 [$iniFile][$section][$option][$value]"
    fi
    unset iniFile section option value iniOptions iniSections allSections sectionFlag sectionNum temp
}
 

function get_section_list(){
    local iniFile=$1
    local iniSections=()
    local allSections
    
    #检查文件
    if ! _check_file ${iniFile};then
        return 1
    fi
    #读取所有字段名并成数组
    allSections=$(awk -F '[][]' '/\[.*]/{print $2}' ${iniFile})
    iniSections=(`echo $allSections | awk -v RS='' '{gsub("\n"," "); print}'`)
    echo ${iniSections[@]}
    unset iniFile iniSections allSections
}

#根据字段读取关键字名
function get_key_list(){
    local iniFile=$1
    local section=$2
    local iniOptions=()
    local iniSections=()
    local allSections
    
    #检查文件
    if ! _check_file ${iniFile};then
        return 1
    fi    #读取所有字段名并成数组
    allSections=$(awk -F '[][]' '/\[.*]/{print $2}' ${iniFile})
    iniSections=(`echo $allSections | awk -v RS='' '{gsub("\n"," "); print}'`)
        
    if [[ -z ${section} ]];then
        error "${BLUE}参数错误![${RESET}${YELLOW}参数格式: ${RESET}${RED}${0} <file> <section_name>${RESET}${BLUE}]${RESET}"
            return 1
    fi
    #判断字段名存在
    if [[ ${allSections} =~ ${section} ]];then
        wait
    else
        error "${BLUE}字段名${RESET}${YELLOW}${section}${RESET}${BLUE}不存在!${RESET}"
            return 1
    fi
    
    #读取字段下所有关键字名
    local a=$(awk "/\[${section}\]/{a=1}a==1"  ${iniFile}|sed -e '1d' -e "/^[#;]/d" -e '/^$/d' -e 's/[ \t]*$//g' -e 's/^[ \t]*//g' -e 's/[ ]/@G@/g' -e '/\[/,$d' )
        
    local b=(`echo $a | awk -v RS='' '{gsub("\n"," "); print}'`)
    local n=${#b[@]}
    local i
    for ((i=0,j=0;i<n;i++))
    do
        #剔除非法字符，转换@G@为空格并添加到数组尾
        temp=${b[$i]}
        if [[ -n "${temp}" ]] || [[ "${temp}" != "@G@" ]];then
        
            local temp_n=${temp//@G@/ }
            iniOptions[$j]=${temp_n%%=*}
            unset temp_n
            
            #iniOptions[$j]=${${temp//@G@/ }%%=*}
            ((j++))
         fi
    done
    echo ${iniOptions[@]}
    unset iniFile section iniOptions iniSections allSections a b n i
}






__ini_init__































